#include <string.h>
#include "buffer.h"
#include "frame.h"

//Header
void Header::initDataMinLen(uint16_t l)
{
	H1 = HEADER_FIX_BEGIN;
	V1 = 2;
	L1 = l;
	V2 = 2;
	L2 = l;
	H2 = HEADER_FIX_BEGIN;
}
bool Header::check(void)const
{
	return H1 == HEADER_FIX_BEGIN
		&& H2 == HEADER_FIX_BEGIN
		&& V1 == 2
		&& V2 == 2
		&& L1 == L2;
}
bool Header::append(class Buffer& b)
{
	return b.append(this, sizeof(*this));
}

//Control
void Control::initActiveS2M(CONTROL_FUN_ACTIVE fun)
{
	FUN = fun;
	FCV = 0;
	ACD = 0;
	PRM = CONTROL_PRM_ACT;
	DIR = CONTROL_DIR_S2M;
}
void Control::initPasiveS2M(CONTROL_FUN_PASIVE fun)
{
	FUN = fun;
	FCV = 0;
	ACD = 0;
	PRM = CONTROL_PRM_PAS;
	DIR = CONTROL_DIR_S2M;
}
bool Control::append(class Buffer& b)
{
	return b.append(this, sizeof(*this));
}

//Address
Address::Address(uint16_t a1, uint16_t a2, uint8_t a3)
{
	A1 = a1; 
	A2 = a2; 
	A3 = a3; 
	T0 = 0;
}
void Address::init(uint16_t a1, uint16_t a2, uint8_t a3)
{
	A1 = a1; 
	A2 = a2; 
	A3 = a3; 
	T0 = 0;
}
void Address::init(const string& s, uint16_t a2, uint8_t a3)
{
	region(s); 
	A2 = a2; 
	A3 = a3; 
	T0 = 0;
}
void Address::region(const string& s)
{
	A1 = strtol(s.empty() ? "4301" : s.data(), 0, 16);
}
bool Address::append(class Buffer& b)
{
	return b.append(this, sizeof(*this));
}

//Function
void Function::initConfirm	(void){AFN = FUNCTION_00_CONFIRM;	}
void Function::initDeny		(void){AFN = FUNCTION_00_CONFIRM;	}
void Function::initOneByOne	(void){AFN = FUNCTION_00_CONFIRM;	}
void Function::initLogin	(void){AFN = FUNCTION_02_HEARTBEAT;	}
void Function::initLogout	(void){AFN = FUNCTION_02_HEARTBEAT;	}
void Function::initHeartbeat(void){AFN = FUNCTION_02_HEARTBEAT;	}
void Function::initSetTask	(void){AFN = FUNCTION_04_SETTASK;	}
void Function::initHistory	(void){AFN = FUNCTION_0D_HISTORY;	}
bool Function::append(Buffer& b)
{
	return b.append(this, sizeof(*this));
}

//Sequence
void Sequence::initSingleAck(uint8_t seq)
{
	SEQ = seq & 0x0f;
	CON = SEQUENCE_CON_YES;
	POS = SEQUENCE_POS_ONE;
}
void Sequence::initSingleNack(uint8_t seq)
{
	SEQ = seq & 0x0f;
	CON = SEQUENCE_CON_NO;
	POS = SEQUENCE_POS_ONE;
}
bool Sequence::append(class Buffer& b)
{
	return b.append(this, sizeof(*this));
}

//Frame
void Frame::clear(void)
{
	memset(this, 0, sizeof(*this));
}
void Frame::dataLength(uint16_t len)
{
	header.L1 = header.L2 = len;
}
bool Frame::append(Buffer& b)
{
	return b.append(this, sizeof(*this));
}
uint16_t Frame::commonLength(void)const
{
	return HEADER_DATA_INDEX;
}
uint16_t Frame::dataLength(void)const
{
	return header.L1
	   	 - sizeof(Control)
		 - sizeof(Address)
		 - sizeof(Function)
		 - sizeof(Sequence);
}
uint16_t Frame::frameLength(void)const
{
	return header.L1 + HEADER_HEAD_LENGTH + HEADER_TAIL_LENGTH;
}
bool Frame::checkHeader(void)const
{
	return header.check();
}
int Frame::checkHeader(int ilen)const
{
	if(ilen < HEADER_HEAD_LENGTH)
	{
		return 0;
	}
	if(checkHeader() == false)
	{
		return -1;
	}
	return 1;
}
int Frame::checkFrame(int ilen)
{
	switch(checkHeader(ilen))
	{
		case  0: return 0;
		case  1: break;
		case -1: return -1;
	}
	if(ilen < frameLength() )
	{
		return 0;
	}
	uint8_t cs = 0;
	uint8_t *p = ((uint8_t*)this) + HEADER_HEAD_LENGTH;

	for(int i = 0; i < header.L1; i++)
	{
		cs += *p++;
	}
	if(cs != *p++)
	{
		return -1;
	}
	if(HEADER_FIX_ENDING != *p)
	{
		return -1;
	}
	return 1;
}
string Frame::toString(void)const
{
	string s;
	uint8_t *p = (uint8_t*)this;

	for(int i = 0; i < frameLength(); i++)
	{
		char buf[8];
		snprintf(buf, sizeof(buf), " %02X", p[i]);
		s += buf;
	}
	return s;
}


